package com.example.understandvideo.service;

import com.example.understandvideo.mapper.*;
import com.example.understandvideo.pojo.*;
import com.example.understandvideo.pojo.common.CameraCutPoint;
import com.example.understandvideo.pojo.common.CameraCutResult;
import com.example.understandvideo.pojo.common.ThumbnailResult;
import com.example.understandvideo.pojo.common.TranscodeVideoResult;
import com.example.understandvideo.pojo.request.TaskCreateRequest;
import com.example.understandvideo.pojo.response.CommonResponse;
import com.example.understandvideo.pojo.response.TaskDetailResponse;
import com.google.gson.Gson;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class SmartTaskProcessor {
    private final BlockingQueue<SmartTask> queue = new LinkedBlockingQueue<>(100);
    private volatile boolean running = true;
    private final int THREAD_COUNT = 10;
    @Resource
    private EngineService engineService;
    @Resource
    private SmartTaskDao smartTaskDao;
    @Resource
    private AnalysisTaskDao analysisTaskDao;
    @Resource
    private DemoProcessor demoProcessor;
    @Resource
    private LogService logService;
    @Resource
    private AsrTaskDao asrTaskDao;
    @Resource
    private StrippingTaskDao strippingTaskDao;


    /**
     * 创建线程池，核心10，最大核心30，存活5秒，队列存储2000，拒绝策略直接抛出异常
     */
    private final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(THREAD_COUNT, 30,
            5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100),
            new ThreadPoolExecutor.CallerRunsPolicy());

    public SmartTaskProcessor() {
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.execute(new SmartTaskProcessor.ResultWorker());
        }
    }

    public void put(TaskCreateRequest request) {
        try {
            SmartTask smartTask = new SmartTask();
            smartTask.setTaskName(request.getName());
            smartTask.setTaskStatus(0);
            smartTask.setFilepth(request.getFilepath());
            smartTask.setType(0);
            smartTask.setTag(request.getTag());
            smartTaskDao.insert(smartTask);
            this.queue.put(smartTask);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public CommonResponse list(TaskRequest request) {
        if (Objects.isNull(request) || Objects.isNull(request.getPage()) || Objects.isNull(request.getPageSize())) {
            request.setPage(0);
            request.setPageSize(10);
        }
        Long count = smartTaskDao.count(request);
        if (Objects.isNull(count) || count == 0) {
            return new CommonResponse();
        }
        List<SmartTask> responseList = smartTaskDao.search(request);
        if (Objects.isNull(responseList)) {
            return new CommonResponse();
        }
        CommonResponse<SmartTask> response = new CommonResponse();
        response.setTotal(count);
        response.setResponseList(responseList);
        return response;
    }

    public TaskDetailResponse detail(Long id) {
        SmartTask task = smartTaskDao.selectByPrimaryKey(id);
        TaskDetailResponse response = new TaskDetailResponse();
        StrippingTask strippingTask = strippingTaskDao.selectByPid(id);
        if(Objects.nonNull(strippingTask)){
            Gson gson = new Gson();
            List<String> points = gson.fromJson(strippingTask.getPoints(), List.class);
            response.setThumbnailResult(points);
        }
        if(Objects.nonNull(strippingTask))
        if (task.getType() == 1) {
            AnalysisTask analysisTask = analysisTaskDao.selectByPid(id);

            response.setName(task.getTaskName());
            response.setFilepath(task.getFilepth());
            if (Objects.nonNull(analysisTask)) {
                AsrTask asrTask = asrTaskDao.selectByPid(analysisTask.getId());
                if (Objects.nonNull(asrTask) && Objects.nonNull(asrTask.getContent())) {
                    response.setAsrText(asrTask.getContent());
                }
                response.setResult(analysisTask.getResult());
            }
            response.setId(task.getId());
            return response;
        }
        response.setName(task.getTaskName());
        response.setResult(null);
        response.setAsrText("暂无asr识别内容");
        response.setFilepath(task.getFilepth());
        response.setId(task.getId());
        return response;
    }

    @PreDestroy
    public void stop() throws InterruptedException {
        this.running = false;
        //ExecutorUtil.shutdown(threadPool);
    }

    private class ResultWorker implements Runnable {
        @Override
        public void run() {
            try {
                while (running) {
                    SmartTask smartTask = queue.take();
                    try {
                        if (smartTask.getType() == 0) {
                            //处理主任务，主要生成拆条结果
                            CameraCutResult cameraCutResult = new CameraCutResult();
//                            try {
//                                cameraCutResult = engineService.getCameraCuts(smartTask.getFilepth());
//                            } catch (Exception e) {
//                                logService.logSmartMsg(smartTask.getId(), "拆条异常报错\n"+e.getMessage());
//                            }
                            //生成抽帧
                            ThumbnailResult thumbnailResult = engineService.getPPTThumbnail(smartTask.getFilepth());
                            if(StringUtils.isNotEmpty(thumbnailResult.getResult())){
                                StrippingTask task = new StrippingTask();
                                task.setPoints(thumbnailResult.getResult());
                                task.setTaskId(smartTask.getId());
                                strippingTaskDao.insert(task);
                            }
                            //执行转码任务
                            if (Objects.nonNull(cameraCutResult) && cameraCutResult.getCutPointList() != null && cameraCutResult.getCutPointList().size() > 0) {
                                cameraCutResult.getCutPointList().stream().parallel().forEach(cameraCutPoint -> {
                                    try {
                                        TranscodeVideoResult result = engineService.transcodeVideo(smartTask.getFilepth(), cameraCutPoint);
                                        if (StringUtils.isNotEmpty(result.getFilepath())) {
                                            demoProcessor.put(smartTask.getTaskName() + "-" + cameraCutPoint.getIndex(), result.getFilepath(), smartTask.getTag(), smartTask.getId());
                                        } else if (StringUtils.isNotEmpty(result.getErrorLog())) {
                                            logService.logSmartMsg(smartTask.getId(), result.getErrorLog());
                                        }
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                });
                            } else {
                                demoProcessor.put(smartTask.getTaskName() + "-0", smartTask.getFilepth(), smartTask.getTag(), smartTask.getId());
                                smartTask.setType(1);
                                smartTaskDao.updateType(smartTask);
                            }
                        }
                        smartTask.setTaskStatus(1);
                        smartTaskDao.updateStatus(smartTask);
                    } catch (Exception e) {
                        smartTask.setTaskStatus(2);
                        smartTaskDao.updateStatus(smartTask);
                        log.error("[SmartTaskProcessor] run error,errorMsg={}", e.getMessage());
                    }
                }
            } catch (Exception ex) {
                log.error("[SmartTaskProcessor] run error={}", ex.getMessage());
            }
        }
    }
}
